package com.my.platform.common.utils.number;

import com.my.platform.common.utils.string.StringUtils;
import com.my.platform.core.exception.BusinessException;
import lombok.extern.log4j.Log4j2;

import java.math.BigDecimal;

@Log4j2
public class BigDecimalUtils {

    public static BigDecimal newBigDecimal(String num) {
        if (StringUtils.isBlank(num)) {
            return new BigDecimal("0");
        }
        return setScale(new BigDecimal(num));
    }

    public static BigDecimal newBigDecimal(Number num) {
        if (isEmpty(num)) {
            return new BigDecimal("0");
        }
        return setScale(new BigDecimal(String.valueOf(num)));
    }

    /**
     * 加法  numbers 之和
     *
     * @Author: 汪焰
     * @date: 2020/8/20 18:07
     */
    public static BigDecimal add(Number... numbers) {
        BigDecimal result = BigDecimal.ZERO;
        for (Number number : numbers) {
            if (isEmpty(number)) {
                continue;
            }
            result = result.add(newBigDecimal(number));
        }
        return setScale(result);
    }

    /**
     * 减法 one - number[0] - number[1] - ...
     *
     * @Author: 汪焰
     * @date: 2020/8/20 18:07
     */
    public static BigDecimal subtract(Number one, Number... numbers) {
        if (isNull(one)) {
            throw new BusinessException("BigDecimalUtils 运算减法 被减数为null");
        }
        BigDecimal result = newBigDecimal(one);
        for (Number number : numbers) {
            if (isNull(one)) {
                log.error("---------------error------------------------");
                log.error("numbers:{}", numbers);
                log.error("---------------error------------------------");
                throw new BusinessException("BigDecimalUtils 运算 减法 相减数为null");
            }
            result = result.subtract(newBigDecimal(number));
        }
        return result;
    }

    /**
     * 乘法 numbers 之积
     *
     * @Author: 汪焰
     * @date: 2020/8/20 18:07
     */
    public static BigDecimal multiply(Number... numbers) {
        BigDecimal result = BigDecimal.ONE;
        for (Number number : numbers) {
            if (isNull(number)) {
                log.error("---------------error------------------------");
                log.error("numbers:{}", numbers);
                log.error("---------------error------------------------");
                throw new BusinessException("BigDecimalUtils 运算 乘法 运算数据存在null");
            }
            if (equal(0, number)) {
                return BigDecimal.ZERO;
            }
            result = result.multiply(newBigDecimal(number));
        }
        return result;
    }

    /**
     * 除法 one / number[0] / number[1] / ...
     *
     * @Author: 汪焰
     * @date: 2020/8/20 18:07
     */
    public static BigDecimal divide(Number one, Number... numbers) {
        if (isNull(one)) {
            throw new BusinessException("BigDecimalUtils 运算 除法 被除数不能为null");
        }
        if (equal(0, one)) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = newBigDecimal(one);
        for (Number number : numbers) {
            if (isEmpty(number)) {
                log.error("---------------error------------------------");
                log.error("one:{} ,numbers:{}", one, numbers);
                log.error("---------------error------------------------");
                throw new BusinessException("BigDecimalUtils 运算 除法 除数不能为null或0");
            }
            result = result.divide(newBigDecimal(number), 4, BigDecimal.ROUND_HALF_EVEN);
        }
        return result;
    }

    /**
     * 保留四位小数 并且四舍五入
     */
    private static BigDecimal setScale(BigDecimal num) {
        return num.setScale(4, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 保留四位小数 银行家舍入法 互联网金融行业
     */
    public static BigDecimal setScaleDown(Number num) {
        BigDecimal value = newBigDecimal(num).setScale(4, BigDecimal.ROUND_HALF_EVEN);
        return value;
    }

    /**
     * 保留小数 并且四舍五入
     */
    public static String setScale(Number num, int scale) {
        String value = newBigDecimal(num).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
        return value;
    }

    /**
     * 保留小数 并且四舍五入
     */
    public static BigDecimal setScale(BigDecimal num, int scale) {
        return num.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    public static boolean isEmpty(Number one) {
        if (isNull(one)) {
            return true;
        }
        BigDecimal oneBig = new BigDecimal(String.valueOf(one));
        BigDecimal twoBig = new BigDecimal(0);
        return oneBig.compareTo(twoBig) == 0;
    }

    public static boolean isNull(Number one) {
        if (one == null) {
            return true;
        }
        return false;
    }

    public static boolean equal(Number one, Number two) {
        if (isNull(one) && isNull(two)) {
            return true;
        }
        if (isNull(one) || isNull(two)) {
            return false;
        }
        BigDecimal oneBig = new BigDecimal(String.valueOf(one));
        BigDecimal twoBig = new BigDecimal(String.valueOf(two));
        return oneBig.subtract(twoBig).doubleValue() == 0;
    }

    public static boolean equal(BigDecimal one, BigDecimal two) {
        if (isNull(one) && isNull(two)) {
            return true;
        }
        if (isNull(one) || isNull(two)) {
            return false;
        }
        return one.subtract(two).doubleValue() == 0;
    }

    public static boolean equal(String one, String two) {
        if (StringUtils.isBlank(one) && StringUtils.isBlank(two)) {
            return true;
        }
        if (StringUtils.isBlank(one) || StringUtils.isBlank(two)) {
            return false;
        }
        return equal(newBigDecimal(one), newBigDecimal(two));
    }

    /**
     * 相反数 (num=9 返回-9)(num=-6 返回6)
     */
    public static BigDecimal negate(Number num) {
        return newBigDecimal(num).negate();
    }

    /**
     * 计算出我们售卖的价格
     * 默认价格  合作商折扣价 * 105% = 支付价格（保留两位）
     * 当支付价格 大于 原价  我们就启用原价 这时候 我们是亏本的
     *
     * @Params originalPrice        启用原价
     * @Params channelPrice         合作商给我们的折扣价
     * @Params rate                 我们乘以的费率
     */
    public static BigDecimal calcPayMoney(String originalPrice, String channelPrice, String rate) {
        try {
            if (StringUtils.isBlank(originalPrice) || StringUtils.isBlank(channelPrice) || StringUtils.isBlank(rate)) {
                return BigDecimal.ZERO;
            }
            //默认价格  合作商折扣价 * 105% = 支付价格（保留两位）
            BigDecimal payMoney = multiply(newBigDecimal(channelPrice), newBigDecimal(rate)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //当我们计算的支付价格 大于 原价 ，我们就启用原价 这时候 我们是亏本的
            if (NumberUtils.gt(payMoney, new BigDecimal(originalPrice))) {
                payMoney = new BigDecimal(originalPrice);
            }
            //原平 太原

            return payMoney;
        } catch (Exception e) {
        }
        return null;
    }
}
